package com.example.springboot.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.springboot.common.Constants;
import com.example.springboot.common.Page;
import com.example.springboot.common.Result;
import com.example.springboot.dto.*;
import com.example.springboot.entity.Guide;
import com.example.springboot.entity.Solution;
import com.example.springboot.exception.ServiceException;
import com.example.springboot.mapper.SolutionMapper;
import com.example.springboot.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.springboot.utils.Md2Text;
import com.example.springboot.utils.TimeUtil;
import com.example.springboot.utils.TokenUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class SolutionServiceImpl extends ServiceImpl<SolutionMapper, Solution> implements ISolutionService {

    @Resource
    private ISolutionService solutionService;
    @Resource
    private IUserService userService;
    @Resource
    private ISCollectionService collectionService;
    @Resource
    private ISCommentService commentService;
    @Resource
    private IScoreService scoreService;
    @Resource
    private IGuideService guideService;

    @Override   //用户编辑方案
    public Result insert(Solution solution) {
        QueryWrapper<Solution> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("guide_id",solution.getGuideId());
        Guide guide;
        Solution one;
        try {
            guide = guideService.getById(solution.getGuideId());
            one = solutionService.getOne(queryWrapper);
        }catch (Exception e) {
            throw new ServiceException(Constants.CODE_500,"系统错误");
        }
        if (guide == null || !guide.getUserId().equals(solution.getUserId()))
            return Result.error(Constants.CODE_600,"引导不存在");
        //插入方案
        if (one == null) {
            if (solutionService.saveOrUpdate(solution))
                return Result.success();
            return Result.error(Constants.CODE_600,"保存失败");
        }
        if (solution.getStatement().equals("已发布") || solution.getStatement().equals("回收"))
            return Result.error();
        //更新方案
        solution.setId(one.getId());
        //用户保存草稿
        if (solution.getStatement().equals("未发布")) {
            if (one.getStatement().equals("回收") || one.getStatement().equals("待审核") || one.getStatement().equals("已发布"))
                return Result.error(Constants.CODE_600,"方案状态不符合");
        }
        //用户发布方案
        else if (solution.getStatement().equals("待审核")) {
            if (one.getStatement().equals("回收"))
                return Result.error(Constants.CODE_600,"方案状态不符合");
            else if (one.getStatement().equals("已发布")) {
                solution.setView(0);
                if (solutionService.saveOrUpdate(solution)) {
                    commentService.deleteBySolution(solution.getId());
                    scoreService.deleteBySolution(solution.getId());
                    return Result.success("修改成功");
                } else
                    return Result.error(Constants.CODE_500, "修改失败");
            }
        }
        if (solutionService.saveOrUpdate(solution))
            return Result.success();
        return Result.error(Constants.CODE_600,"保存失败");
    }

    @Override   //根据引导id查找方案
    public Result findByGuide(Integer guide_id) {
        QueryWrapper<Solution> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("guide_id",guide_id);
        return Result.success(solutionService.getOne(queryWrapper));
    }

    @Override   //查找用户的已发布方案
    public List<Solution> findByUserId(Integer userId) {
        QueryWrapper<Solution> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        queryWrapper.eq("statement","已发布");
        List<Solution> result = solutionService.list(queryWrapper);
        result.sort(Comparator.comparing(Solution::getCreateTime).reversed());
        return result;
    }

    @Override   //个人中心方案管理
    public List<SolCenterDTO> getCenter(Integer userId) {
        QueryWrapper<Solution> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        List<Solution> solutionList = solutionService.list(queryWrapper);
        solutionList.sort(Comparator.comparing(Solution::getCreateTime).reversed());
        List<SolCenterDTO> solCenterDTOS = new ArrayList<>();
        for (Solution solution : solutionList) {
            SolCenterDTO solCenterDTO = new SolCenterDTO();
            solCenterDTO.setId(solution.getId());
            solCenterDTO.setName(solution.getName());
            solCenterDTO.setView(solution.getView());
            solCenterDTO.setDetail(Md2Text.convert(solution.getDetail()));
            solCenterDTO.setGuideId(solution.getGuideId());
            solCenterDTO.setStatement(solution.getStatement());

            solCenterDTO.setGuideName(guideService.getById(solution.getGuideId()).getName());
            solCenterDTO.setCollections(collectionService.getCount(solution.getId()));
            solCenterDTO.setComments(commentService.getCount(solution.getId()));
            solCenterDTO.setRelativeTime(TimeUtil.createRelative(solution.getCreateTime()));
            solCenterDTOS.add(solCenterDTO);
        }
        return solCenterDTOS;
    }

    @Override   //根据用户id查找其所有方案的浏览量总和
    public int getViewByUser(Integer userId) {
        QueryWrapper<Solution> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        List<Solution> solutionList = solutionService.findByUserId(userId);
        int view = 0;
        for (Solution solution : solutionList) {
            if (solution.getStatement().equals("已发布"))
                view += solution.getView();
        }
        return view;
    }

    @Override   //方案详情
    public SolutionInfoDTO getDetailById(Integer id) {
        if (id == null)
            throw new ServiceException(Constants.CODE_500,"系统错误");
        Solution solutionById;
        try {
            solutionById = solutionService.getById(id);
        }catch (Exception e) {
            throw new ServiceException(Constants.CODE_500,"系统错误");
        }
        if (solutionById == null)
            throw new ServiceException(Constants.CODE_600,"未找到方案");
        SolutionInfoDTO solution = new SolutionInfoDTO();
        SolutionDTO solutionDTO = new SolutionDTO();
        //设置solutionDTO
        solutionDTO.setId(id);
        solutionDTO.setName(solutionById.getName());
        solutionDTO.setView(solutionById.getView());

        solution.setSolutionDTO(solutionDTO);
        solution.setDetail(solutionById.getDetail());
        solution.setUserSolutionDTO(userService.getUserSolutionDTO(solutionById.getUserId(),id));
        solution.setMine(Objects.requireNonNull(TokenUtils.getCurrentUser()).getId().equals(solution.getUserSolutionDTO().getUserDTO().getId()));
        solution.setCreateTime(solutionById.getCreateTime());
        solution.setRelativeTime(TimeUtil.createRelative(solutionById.getCreateTime()));
        solution.setCollections(collectionService.getCount(id));
        return solution;
    }

    @Override   //根据关键词查找社区中所有已发布方案，按时间、收藏、浏览排序
    public HashMap<String, Page> findAllBySearch(Integer pageNum,Integer pageSize,String words) {
        QueryWrapper<Solution> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("statement","已发布");
        List<Solution> solutionList = solutionService.list(queryWrapper);
        solutionList.sort(Comparator.comparing(Solution::getCreateTime).reversed());
        List<SolutionAllDTO> solutionAllDTOS = new ArrayList<>();
        HashMap<String,Page> hashMap = new HashMap<>();
        for (Solution solution : solutionList) {
            SolutionAllDTO solutionAllDTO = new SolutionAllDTO();
            UserDTO userDTO = userService.getUserDTO(solution.getUserId());

            solutionAllDTO.setId(solution.getId());
            solutionAllDTO.setName(solution.getName());
            solutionAllDTO.setView(solution.getView());
            solutionAllDTO.setUserDTO(userDTO);
            solutionAllDTO.setScore(scoreService.getScore(solution.getId()));

            String content = Md2Text.convert(solution.getDetail());

            if (content.length() <= 150){
                solutionAllDTO.setDetail(content);
            }
            else {
                solutionAllDTO.setDetail(content.substring(0,150) + "……");
            }
            solutionAllDTO.setCreateTime(solution.getCreateTime().toLocalDate());
            solutionAllDTO.setRelativeTime(TimeUtil.createRelative(solution.getCreateTime()));
            solutionAllDTO.setComments(commentService.getCount(solution.getId()));
            solutionAllDTO.setCollections(collectionService.getCount(solution.getId()));

            solutionAllDTOS.add(solutionAllDTO);
        }
        //关键词匹配
        List<SolutionAllDTO> timeList = new ArrayList<>();
        List<SolutionAllDTO> viewList = new ArrayList<>();
        List<SolutionAllDTO> collectionList = new ArrayList<>();
        if (StrUtil.isBlank(words)) {
            timeList = new ArrayList<>(solutionAllDTOS);
            viewList = new ArrayList<>(solutionAllDTOS);
            collectionList = new ArrayList<>(solutionAllDTOS);
        }
        else {
            Pattern pattern = Pattern.compile(words,Pattern.CASE_INSENSITIVE);
            for (SolutionAllDTO solutionAllDTO : solutionAllDTOS) {
                Matcher matcher1 = pattern.matcher(solutionAllDTO.getName());
                Matcher matcher2 = pattern.matcher(solutionAllDTO.getUserDTO().getNickname());
                if (matcher1.find() || matcher2.find()) {
                    timeList.add(solutionAllDTO);
                }
            }
            if (timeList.isEmpty()) {
                return null;
            }
            viewList = new ArrayList<>(timeList);
            collectionList = new ArrayList<>(timeList);
        }
        viewList.sort((t1,t2)->t2.getView().compareTo(t1.getView()));
        collectionList.sort((t1,t2)->t2.getCollections().compareTo(t1.getCollections()));

        Page page = new Page();
        hashMap.put("time",page.startPage(timeList,pageNum,pageSize));
        hashMap.put("view",page.startPage(viewList,pageNum,pageSize));
        hashMap.put("collection",page.startPage(collectionList,pageNum,pageSize));

        return hashMap;
    }

    @Override   //更新访问量
    public Integer updateView(Integer id) {
        Solution solution = solutionService.getById(id);
        solution.setView(solution.getView() + 1);
        solutionService.saveOrUpdate(solution);
        return solution.getView();
    }

    @Override   //个人主页发布的方案
    public List<SolutionAllDTO> getSolutionHomes(Integer userId) {
        QueryWrapper<Solution> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("statement","已发布");
        queryWrapper.eq("user_id",userId);
        List<Solution> solutionList = solutionService.list(queryWrapper);
        List<SolutionAllDTO> solutionAllDTOS = new ArrayList<>();
        for (Solution solution : solutionList) {
            SolutionAllDTO solutionAllDTO = new SolutionAllDTO();
            solutionAllDTO.setId(solution.getId());
            solutionAllDTO.setName(solution.getName());

            String content = Md2Text.convert(solution.getDetail());
            if (content.length() <= 150){
                solutionAllDTO.setDetail(content);
            }
            else {
                solutionAllDTO.setDetail(content.substring(0,150) + "……");
            }
            solutionAllDTO.setScore(scoreService.getScore(solution.getId()));
            solutionAllDTO.setView(solution.getView());
            solutionAllDTO.setCreateTime(solution.getCreateTime().toLocalDate());
            solutionAllDTO.setComments(commentService.getCount(solution.getId()));
            solutionAllDTO.setCollections(collectionService.getCount(solution.getId()));
            solutionAllDTO.setRelativeTime(TimeUtil.createRelative(solution.getCreateTime()));
            solutionAllDTOS.add(solutionAllDTO);
        }
        solutionAllDTOS.sort(Comparator.comparing(SolutionAllDTO::getCreateTime).reversed());
        return solutionAllDTOS;
    }

    @Override   //根据方案id删除方案及其评论、收藏、打分
    public boolean removeSolutionInfo(Integer id) {
        Solution one = getOneById(id);
        if (one.getStatement().equals("回收")) {
            boolean result = solutionService.removeById(id);
            collectionService.deleteBySolution(id);
            commentService.deleteBySolution(id);
            scoreService.deleteBySolution(id);
            return result;
        }
        else
            throw new ServiceException(Constants.CODE_600,"方案状态不符合");
    }

    @Override   //根据引导id删除方案及相关信息
    public boolean removeSolutionByGuide(Integer guideId) {
        QueryWrapper<Solution> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("guide_id",guideId);
        Solution solution = solutionService.getOne(queryWrapper);
        if (solution != null) {
            if (solutionService.removeById(solution.getId())) {
                collectionService.deleteBySolution(solution.getId());
                commentService.deleteBySolution(solution.getId());
                scoreService.deleteBySolution(solution.getId());
                return true;
            }
        }
        return false;
    }

    @Override   //管理员审核通过方案
    public Result toPublish(Integer id) {
        Solution find = solutionService.getById(id);
        Solution solution = new Solution();
        solution.setId(id);
        if (find == null)
            return Result.error(Constants.CODE_500,"未找到该方案");
        if (!find.getStatement().equals("待审核"))
            return Result.error(Constants.CODE_500,"方案状态不为待审核");
        solution.setStatement("已发布");
        solution.setCreateTime(LocalDateTime.now());
        if (solutionService.saveOrUpdate(solution))
            return Result.success("发布成功");
        else
            return Result.error(Constants.CODE_500,"发布失败");
    }

    @Override   //管理员打回方案
    public Result toUnPublish(Integer id) {
        Solution find = solutionService.getById(id);
        Solution solution = new Solution();
        solution.setId(id);
        if (find == null)
            return Result.error(Constants.CODE_500,"未找到该方案");
        if (!find.getStatement().equals("已发布") && !find.getStatement().equals("待审核"))
            return Result.error(Constants.CODE_500,"方案状态不为已发布和待审核");
        else {
            if (find.getStatement().equals("已发布")) {
                solution.setStatement("未发布");
                solution.setView(0);
                if (solutionService.saveOrUpdate(solution)) {
                    commentService.deleteBySolution(id);
                    scoreService.deleteBySolution(id);
                    return Result.success("修改成功");
                }
                else
                    return Result.error(Constants.CODE_500,"修改失败");
            }
            else {
                solution.setStatement("未发布");
                if (solutionService.saveOrUpdate(solution)) {
                    return Result.success("修改成功");
                }
                else
                    return Result.error(Constants.CODE_500,"修改失败");
            }
        }
    }

    @Override   //管理员获取已发布方案列表
    public Result adminGetPublished(int PageNum, int PageSize, Integer userId, String name, String sortWay) {
        QueryWrapper<Solution> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("statement","已发布");
        if (userId != null)
            queryWrapper.eq("user_id",userId);
        queryWrapper.like("name",name);
        List<Solution> solutionList = solutionService.list(queryWrapper);
        Page page = new Page();
        if (sortWay.equals("new"))
            solutionList.sort(Comparator.comparing(Solution::getCreateTime).reversed());
        else
            solutionList.sort(Comparator.comparing(Solution::getCreateTime));
        return Result.success(page.startPage(solutionList,PageNum,PageSize));
    }

    @Override   //管理员获取待审核方案列表
    public Result adminGetToExamine(int PageNum, int PageSize, Integer userId, String name) {
        QueryWrapper<Solution> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("statement","待审核");
        if (userId != null)
            queryWrapper.eq("user_id",userId);
        queryWrapper.like("name",name);
        Page page = new Page();
        return Result.success(page.startPage(solutionService.list(queryWrapper),PageNum,PageSize));
    }

    @Override   //用户管理方案仓库
    public Result manageSolution(Solution solution) {
        Solution one = getOneById(solution.getId());
        if (one == null || !one.getUserId().equals(solution.getUserId()))
            return Result.error(Constants.CODE_600,"方案不存在");

        switch (solution.getStatement()) {
            //方案设为私密
            case "未发布":
                if (one.getStatement().equals("回收") || one.getStatement().equals("未发布"))
                    return Result.error(Constants.CODE_600, "方案状态不符合");
                else if (one.getStatement().equals("已发布")) {
                    solution.setView(0);
                    if (solutionService.saveOrUpdate(solution)) {
                        commentService.deleteBySolution(solution.getId());
                        scoreService.deleteBySolution(solution.getId());
                        return Result.success("修改成功");
                    } else
                        return Result.error(Constants.CODE_500, "修改失败");
                }
                break;
            //用户发布方案
            case "待审核":
                if (one.getStatement().equals("回收") || one.getStatement().equals("待审核") || one.getStatement().equals("已发布"))
                    return Result.error(Constants.CODE_600, "方案状态不符合");
                break;
            //用户将方案加入回收站
            case "回收":
                if (one.getStatement().equals("回收"))
                    return Result.error(Constants.CODE_600, "方案状态不符合");
                else if (one.getStatement().equals("已发布")) {
                    solution.setView(0);
                    if (solutionService.saveOrUpdate(solution)) {
                        commentService.deleteBySolution(solution.getId());
                        scoreService.deleteBySolution(solution.getId());
                        return Result.success("修改成功");
                    } else
                        return Result.error(Constants.CODE_500, "修改失败");
                }
                break;
        }
        if (saveOrUpdate(solution))
            return Result.success("操作成功");
        return Result.error(Constants.CODE_500,"修改失败");
    }

    @Override
    public void export(Integer guideId, HttpServletResponse response) {
        Integer userId = Objects.requireNonNull(TokenUtils.getCurrentUser()).getId();
        QueryWrapper<Solution> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("guide_id",guideId);
        Guide guide;
        Solution one;
        try {
            guide = guideService.getById(guideId);
            one = solutionService.getOne(queryWrapper);
        }catch (Exception e) {
            throw new ServiceException(Constants.CODE_500,"系统错误");
        }
        if (guide == null || !guide.getUserId().equals(userId))
            throw new ServiceException(Constants.CODE_600,"参数错误");
        if (one == null)
            throw new ServiceException(Constants.CODE_600,"解决方案不存在");
        String content = Md2Text.convertMd(one.getDetail());
        response.setCharacterEncoding("utf-8");
        //设置响应的内容类型
        response.setContentType("text/plain");
        String fileName = URLEncoder.encode("文件名称", StandardCharsets.UTF_8);
        //设置文件的名称和格式
        response.addHeader("Content-Disposition","attachment;filename=" + fileName + ".txt");
        BufferedOutputStream buff = null;
        ServletOutputStream outStr = null;
        try {
            outStr = response.getOutputStream();
            buff = new BufferedOutputStream(outStr);
            buff.write(content.getBytes(StandardCharsets.UTF_8));
            buff.flush();
            buff.close();
        } catch (Exception e) {
            throw new ServiceException(Constants.CODE_500,"导出文件文件出错");
        } finally {try {
            assert buff != null;
            buff.close();
            outStr.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        }
    }

    @Override   //用户从回收站恢复方案
    public Result recoverySolution(Solution solution) {
        Solution one = getOneById(solution.getId());
        if (one == null || !one.getUserId().equals(solution.getUserId()))
            return Result.error(Constants.CODE_600,"方案不存在");
        if (solution.getStatement().equals("未发布") && one.getStatement().equals("回收")) {
            if (saveOrUpdate(solution))
                return Result.success("恢复成功");
        }
        return Result.error(Constants.CODE_600,"方案状态不符合");
    }

    private Solution getOneById(Integer id) {
        Solution one;
        try {
            one = solutionService.getById(id);
        } catch (Exception e) {
            throw new ServiceException(Constants.CODE_500,"系统错误");
        }
        return one;
    }
}
